package com.hunyuan.player;

import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.util.List;

/**
 * Created by hunyuan on 2017/1/17.
 */

public class PlayService extends Service implements PlaybackManager.PlaybackServiceCallback {

    public static final String MEDIA_ID_ROOT = "__ROOT__";

    private static final String TAG = PlayService.class.getSimpleName();

    public static final String ACTION_CMD = "com.hunyuan.player.ACTION_CMD";
    public static final String CMD_NAME = "CMD_NAME";
    public static final String CMD_PAUSE = "CMD_PAUSE";
    private static final int STOP_DELAY = 30000;

    private final IBinder binder = new MyBinder();

    private final DelayedStopHandler mDelayedStopHandler = new DelayedStopHandler(this);
    private NotificationManager mNotificationManager;
    private PlaybackManager mPlaybackManager;
    private MediaSessionCompat mSession;

    @Override
    public void onCreate() {
        super.onCreate();

        LocalPlayback localPlayback = new LocalPlayback(this);
        QueueManager queueManager = new QueueManager(new QueueManager.MetadataUpdateListener() {
            @Override
            public void onMetadataChanged(MediaMetadataCompat metadata) {
                mSession.setMetadata(metadata);
            }

            @Override
            public void onMetadataRetrieveError() {
                mPlaybackManager.updatePlaybackState("无数据");
            }

            @Override
            public void onCurrentQueueIndexUpdated(int queueIndex) {
                mPlaybackManager.handlePlayRequest();
            }

            @Override
            public void onQueueUpdated(String title, List<MediaSessionCompat.QueueItem> newQueue) {
                mSession.setQueue(newQueue);
                mSession.setQueueTitle(title);
            }
        });

        mPlaybackManager = new PlaybackManager(this, queueManager, localPlayback);

        mSession = new MediaSessionCompat(this, "PlayService");
        mSession.setCallback(mPlaybackManager.getMediaSessionCallback());
        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

        Context context = getApplicationContext();
        Intent intent = new Intent(context, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(context, 99,
                intent, PendingIntent.FLAG_UPDATE_CURRENT);
        mSession.setSessionActivity(pi);

        mPlaybackManager.updatePlaybackState(null);

        try {
            mNotificationManager = new NotificationManager(this);
        } catch (RemoteException e) {
            throw new IllegalStateException("Could not create a MediaNotificationManager", e);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            String action = intent.getAction();
            String command = intent.getStringExtra(CMD_NAME);
            if (ACTION_CMD.equals(action)) {
                if (CMD_PAUSE.equals(command)) {
                    mPlaybackManager.handlePauseRequest();
                }
            } else {
                MediaButtonReceiver.handleIntent(mSession, intent);
            }
        }

        mDelayedStopHandler.removeCallbacksAndMessages(null);
        mDelayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy: ");

        mPlaybackManager.handleStopRequest(null);
        mNotificationManager.stopNotification();

        mDelayedStopHandler.removeCallbacksAndMessages(null);
        mSession.release();
    }

    // ----------- PlaybackServiceCallback 接口 -----------

    @Override
    public void onPlaybackStart() {
        mSession.setActive(true);

        mDelayedStopHandler.removeCallbacksAndMessages(null);

        startService(new Intent(getApplicationContext(), PlayService.class));
    }

    @Override
    public void onNotificationRequired() {
        mNotificationManager.startNotification();
    }

    @Override
    public void onPlaybackStop() {
        mSession.setActive(false);
        mDelayedStopHandler.removeCallbacksAndMessages(null);
        mDelayedStopHandler.sendEmptyMessageDelayed(0, STOP_DELAY);
        stopForeground(true);
    }

    @Override
    public void onPlaybackStateUpdated(PlaybackStateCompat newState) {
        mSession.setPlaybackState(newState);
    }


    // ------------

    public MediaSessionCompat.Token getSessionToken() {
        if (mSession != null)
            return mSession.getSessionToken();
        return null;
    }

    private static class DelayedStopHandler extends Handler {
        private final WeakReference<PlayService> mWeakReference;

        private DelayedStopHandler(PlayService service) {
            mWeakReference = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            PlayService service = mWeakReference.get();
            if (service != null && service.mPlaybackManager.getPlayback() != null) {
                if (service.mPlaybackManager.getPlayback().isPlaying()) {
                    Log.d(TAG, "Ignoring delayed stop since the media player is in use.");
                    return;
                }
                Log.d(TAG, "Stopping service with delay handler.");
                service.stopSelf();
            }
        }
    }

    public class MyBinder extends Binder {
        PlayService getPlayService() {
            return PlayService.this;
        }
    }
}
